package executor;

import utils.ExceptionUtils;

import java.util.List;
import java.util.concurrent.*;

//         6-15 使用CompletionService，使页面在下载完成后立即显示出来
public abstract class Renderer {
    //CompletionService将Executor与BlockingQueue的功能融合在一起
    private final ExecutorService executor;

    Renderer(ExecutorService executor) {
        this.executor = executor;
    }

    void renderPage(CharSequence source) {
        List<ImageInfo> info = scanForImageInfo(source);
        //ExecutorCompletionService实现了CompletionService，并将计算部分委托给一个Executor。
        CompletionService<ImageData> completionService = new ExecutorCompletionService<ImageData>(executor);
        for (final ImageInfo imageInfo : info)
            //提交一个带返回值的任务，并且返回一个代表即将得到任务的结果的Future
            completionService.submit(new Callable<ImageData>() {
                public ImageData call() {
                    return imageInfo.downloadImage(); //CompletionService中有类似队列的操作
                }
            });
        renderText(source);
        try {
            //通过CompletionService中获取结果以及使每张图片在下载完成后立刻显示出来
            for (int t = 0, n = info.size(); t < n; t++) {
                //取得并移除已完成任务，如果没有则等待
                Future<ImageData> f = completionService.take();
                ImageData imageData = f.get();
                renderImage(imageData);
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } catch (ExecutionException e) {
            throw ExceptionUtils.launderThrowable(e.getCause());
        }
    }

    interface ImageData {
    }

    interface ImageInfo {
        ImageData downloadImage();
    }

    abstract void renderText(CharSequence s);

    abstract List<ImageInfo> scanForImageInfo(CharSequence s);

    abstract void renderImage(ImageData i);
}
